package com.pine.app.module.security.oauth.plugin.impl.loginAttemp;


import com.pine.app.module.security.core.common.AuthConstant;
import com.pine.app.module.security.oauth.config.properties.LoginProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.util.concurrent.TimeUnit;

/**
 * @author xyjxust
 * @create 2019/3/15 9:59
 **/
@Slf4j
public class RedisLoginAttempServiceImpl implements LoginAttempService {
    private static final String LOGIN_FAIL_TIMES = AuthConstant.CACHE_NAMESPACE + "LOGIN_FAIL_TIMES:";
    private RedisTemplate<String, Object> redisTemplate;
    private LoginProperties oauthProperty;

    public RedisLoginAttempServiceImpl(RedisTemplate<String, Object> redisTemplate, LoginProperties oauthProperty) {
        this.redisTemplate = redisTemplate;
        this.oauthProperty = oauthProperty;
    }


    @Override
    public void loginSucceeded(String key) {
        redisTemplate.delete(LOGIN_FAIL_TIMES + key);
    }

    @Override
    public void loginFailed(String key) {
        redisTemplate.opsForValue().increment(LOGIN_FAIL_TIMES + key, 1);
        redisTemplate.expire(LOGIN_FAIL_TIMES + key, oauthProperty.getAttemp().getExpire(), TimeUnit.MILLISECONDS);
    }

    @Override
    public boolean isBlocked(String key) {
        try {
            return loginTimes(key) >= oauthProperty.getAttemp().getTimers();
        } catch (Exception e) {
            log.error("登陆错误次数判断是否大于最大指错误", e);
            return false;
        }
    }

    @Override
    public int loginTimes(String key) {
        try {
            return (int) (getKey(LOGIN_FAIL_TIMES+key));
        } catch (Exception e) {
            log.error("获取登陆错误次数错误", e);
            return 0;
        }
    }

    private long getKey(final String key) {
        return redisTemplate.execute((RedisCallback<Long>) connection -> {
            RedisSerializer<String> redisSerializer =  redisTemplate.getStringSerializer();
            RedisSerializer<String> keySerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
            byte[] rowkey = keySerializer.serialize(key);
            byte[] rowval = connection.get(rowkey);
            try {
                String val = redisSerializer.deserialize(rowval);
                return Long.parseLong(val);
            } catch (Exception e) {
                return 0L;
            }finally {
                connection.close();
            }
        });
    }
}
